﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GraphViewer.Entity;
using GraphViewer.Configuration;
using System.Xml.Linq;
using System.Globalization;
using System.IO;

namespace GraphViewer.Data
{
    public class ControlMLoader
    {
        public static List<ProcessEntity> Read(string fileName)
        {
            XDocument document = XDocument.Load(fileName);
            List<XElement> elements = new List<XElement>();
            List<ProcessEntity> processes = new List<ProcessEntity>();
            StringBuilder sb = new StringBuilder();

            var nodes = document.Descendants().Where(n => n.Name.LocalName == "JOB").OrderBy(e => e.Attribute("JOBNAME").Value);

            foreach (var jobNode in nodes)
            {
                XElement element = EqualizeElement(jobNode);
                elements.Add(element);

                ProcessEntity entity = new ProcessEntity();
                entity.ProcessName = jobNode.Attribute("DESCRIPTION").Value.ToString();
                entity.ProcessId = jobNode.Attribute("JOBNAME").Value.ToString();
                entity.JobName = jobNode.Attribute("JOBNAME").Value.ToString();
                entity.GroupName = jobNode.Attribute("GROUP").Value.ToString();
                entity.TaskType = jobNode.Attribute("TASKTYPE").Value.ToString();

                sb.Append(entity.JobName + " | " + entity.ProcessName + Environment.NewLine);                

                int seed = 0;
                string name = entity.GroupName.Length > 2 ? entity.GroupName.Substring(entity.GroupName.Length - 2) : entity.GroupName;

                if (int.TryParse(name, out seed))
                    entity.GroupId = seed.ToString();
                else
                    entity.GroupId = entity.GroupName.Replace("NORISKSG", "");

                foreach (var dependencyNode in jobNode.Elements().Where(n => n.Name.LocalName == "INCOND"))
                {
                    string dependencyName = dependencyNode.Attribute("NAME").Value.Replace("#", "");
                    string[] jobs = dependencyName.Split('-');

                    if (jobs.Length == 2 && jobs[1] == entity.ProcessId)
                    {
                        var predecessor = nodes.ToList().Find(n => n.Attribute("JOBNAME").Value == jobs[0]);

                        if (predecessor != null)
                        {
                            entity.Predecessors.Add(FindProcessId(predecessor));
                        }
                        else
                        {
                            entity.Predecessors.Add(jobs[0]);
                        }
                    }
                }

                foreach (var dependencyNode in jobNode.Elements().Where(n => n.Name.LocalName == "OUTCOND" && n.Attributes().Any(a => a.Name.LocalName == "SIGN" && a.Value == "ADD")))
                {
                    string[] jobs = dependencyNode.Attribute("NAME").Value.Split('-');

                    var successor = nodes.ToList().Find(n => n.Attribute("JOBNAME").Value == jobs[1]);

                    if (successor != null)
                    {
                        entity.Successors.Add(FindProcessId(successor));
                    }
                    else
                    {
                        entity.Successors.Add(jobs[1]);
                    }
                }

                entity.ProcessId = FindProcessId(jobNode);

                processes.Add(entity);
            }

            Save(document, elements, fileName);

            //WriteProcessDependency(processes);

            //File.WriteAllText(@"C:\a.txt", sb.ToString());

            return processes;
        }

        private static string FindProcessId(XElement jobName)
        {
            string processName = string.Empty;

            if (jobName.Elements().Any(n => n.Name.LocalName == "AUTOEDIT2" && n.Attributes().Any(a => a.Name.LocalName == "NAME")))
            {
                int processId = 0;
                var parameterNode = jobName.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.Equals("%%PARM5")).SingleOrDefault();

                if (parameterNode != null)
                {
                    processName = parameterNode.Attribute("VALUE").Value.Replace("-id:", "");

                    if (int.TryParse(processName, out processId))
                    {
                        processName = processId.ToString();
                    }
                    else
                    {
                        processName = string.Empty;
                    }
                }
            }

            if (string.IsNullOrEmpty(processName))
            {
                processName = jobName.Attribute("JOBNAME").Value;
            }

            return processName;
        }

        public static void Export(List<ProcessEntity> processes, string fileName, string system, string environment)
        {
            EnvironmentConfigurationSection _environmentConfiguration = EnvironmentConfigurationSection.GetSection();

            if (_environmentConfiguration.Systems[system] == null)
                return;

            ControlMConfigurationElement controlMConfiguration = _environmentConfiguration.Systems[system].ControlM[environment];

            XDocument document = new XDocument(
                    new XDeclaration("1.0", "ISO-8859-1", "no"),
                    new XDocumentType("DEFTABLE", null, "deftable.dtd", null),
                    XElement.Parse(@"                
                            <DEFTABLE>
                                <TABLE DATACENTER='BBACTMC2' TABLE_NAME='BBAMTSN_NLB_RSCI_SYSTEM' TABLE_USERDAILY='SYSTEM' USED_BY_CODE='0'>
                                </TABLE>
                            </DEFTABLE>")
                    );

            document.Declaration = new XDeclaration("1.0", "ISO-8859-1", null);

            string elementBase = @"
                <JOB APPLICATION='BBAMTSN_NLB_RSCI' APR='1' AUG='1' AUTHOR='odlopes' AUTOARCH='0' CHANGE_DATE='20130115' CHANGE_TIME='150513' CHANGE_USERID='odlopes' CONFIRM='0' CREATION_DATE='20130115' CREATION_TIME='150513' CREATION_USER='odlopes' CRITICAL='0' CYCLIC='0' CYCLIC_TOLERANCE='0' CYCLIC_TYPE='Interval' DAYS_AND_OR='OR' DEC='1' DESCRIPTION='PREPARAR PROCESSAMENTO - GRP_001 ITAU: CARGA DAS OPERACOES' FEB='1' GROUP='NORISKSG01' IND_CYCLIC='START' INTERVAL='00001M' JAN='1' JOBNAME='RSCIS065DP' JUL='1' JUN='1' MAR='1' MAXDAYS='0' MAXRERUN='0' MAXRUNS='0' MAXWAIT='30' MAY='1' MEMLIB='\\%%PARM51.\JOBCTL\%%PARM9.\%%PARM50.\SHELLIB' MEMNAME='EXEC_PROG_RSCI.cmd' MULTY_AGENT='N' NODEID='BBARISCO' NOV='1' OCT='1' OPTION='Copy' OWNER='controlm' PAR='\\%%PARM51.\JOBCTL\%%PARM9.\%%PARM50.\LOG\%%JOBNAME._%%ODATE..TXT' PARENT_TABLE='BBAMTSN_NLB_RSCI_SYSTEM' PRIORITY='AA' RETRO='0' RULE_BASED_CALENDAR_RELATIONSHIP='OR' SEP='1' SHIFT='IGNOREJOB' SHIFTNUM='+00' SYSDB='0' TASKTYPE='Job' USE_INSTREAM_JCL='N' WEEKDAYS='1,2,3,4,5' WEEKSCAL='ALLDAYS' DOCLIB='http://gsti.itau/maximo/ui/?event=loadapp&amp;value=change&amp;uniqueid=4288596&amp;uisessionid=804'>
                    <QUANTITATIVE NAME='INIT' QUANT='1' />
                    <QUANTITATIVE NAME='RSCI_PROD' QUANT='1' />
                    <AUTOEDIT2 NAME='%%PARM1' VALUE='%%JOBNAME' />
                    <AUTOEDIT2 NAME='%%PARM2' VALUE='ibba.src.console.exe' />
                    <AUTOEDIT2 NAME='%%PARM3' VALUE='-servidor:%%COMPUTERNAME%%' />
                    <AUTOEDIT2 NAME='%%PARM4' VALUE='-tipo:comando' />
                    <AUTOEDIT2 NAME='%%PARM5' VALUE='-id:RSCISI01DP' />
                    <AUTOEDIT2 NAME='%%PARM50' VALUE='RSCI' />
                    <AUTOEDIT2 NAME='%%PARM51' VALUE='BBACTMC2' />
                    <AUTOEDIT2 NAME='%%PARM6' VALUE='-ref:%%$OYEAR.-%%OMONTH.-%%ODAY.' />
                    <AUTOEDIT2 NAME='%%PARM9' VALUE='PRODUCAO' />
                    <CONTROL NAME='EXPURGO_RSCI_EVENTUAL' TYPE='S' />
                    <ON CODE='*MSG_Sucesso*' STMT='*'>
                        <DO ACTION='OK' />                        
                        <DOMAIL ATTACH_SYSOUT='Yes' DEST='{0}' MESSAGE='{0}: Sucesso no programa %%PARM2., consultar anexo. -- Job = %%JOBNAME %%PARM5 %%PARM6' SUBJECT='[CTM] *** Sucesso: RSCI - {0} ***' URGENCY='R'/>
                    </ON>
                    <ON CODE='*MSG_Semarq_Prog*' STMT='*'>
                        <DO ACTION='NOTOK' />
                        <DOMAIL ATTACH_SYSOUT='Yes' DEST='{0}' MESSAGE='{0}: Programa %%PARM2. nao encontrado no diretorio -- Job = %%JOBNAME %%PARM5 %%PARM6' SUBJECT='[CTM] *** Alerta de Erro : RSCI - {0} ***' URGENCY='V' />
                    </ON>
                    <ON CODE='*MSG_ErroProg*' STMT='*'>
                        <DO ACTION='NOTOK' />
                        <DOMAIL ATTACH_SYSOUT='Yes' DEST='{0}' MESSAGE='{0}: Erro no programa %%PARM2., consultar anexo. -- Job = %%JOBNAME %%PARM5 %%PARM6' SUBJECT='[CTM] *** Alerta de Erro: RSCI - {0} ***' URGENCY='V' />
                    </ON>
                    <SHOUT DEST='ECS' MESSAGE='Sr. Operador - O Job %%JOBNAME esta executando 20 minutos acima da média histórica de sua execução.' TIME='+020' URGENCY='R' WHEN='EXECTIME' />
                    <SHOUT DEST='ECS' MESSAGE='Sr. Operador - O Job %%JOBNAME esta executando 40 minutos acima da média histórica de sua execução.' TIME='+040' URGENCY='U' WHEN='EXECTIME' />
                </JOB>
                ";

            var tableElement = document.Descendants().Where(n => n.Name.LocalName == "TABLE").First();
            tableElement.Attribute("TABLE_NAME").Value = controlMConfiguration.TableName;

            foreach (var process in processes.Where(p => !p.IsExternalJob))
            {
                string description = ("GRP_" + process.GroupId.PadLeft(3, '0') + " " + process.ProcessName).RemoveAccents();
                string jobName = ReplaceJobName(process.JobName, process.TaskType, controlMConfiguration.JobNameSuffix);

                XElement element = XElement.Parse(elementBase);

                element.Attribute("DESCRIPTION").Value = description;
                element.Attribute("JOBNAME").Value = jobName.Replace("#", "");
                element.Attribute("PARENT_TABLE").Value = controlMConfiguration.TableName;
                element.Attribute("GROUP").Value = process.GroupId == "liberarisco" ? "liberarisco" : "NORISKSG" + process.GroupId.PadLeft(2, '0');
                element.Attribute("TASKTYPE").Value = process.TaskType.Replace("Maybe", "");
                element.Attribute("NODEID").Value = controlMConfiguration.NodeId;
                element.Attribute("APPLICATION").Value = controlMConfiguration.Application;

                element.Attribute("CHANGE_DATE").Value = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0');
                element.Attribute("CHANGE_TIME").Value = DateTime.Now.Hour.ToString().PadLeft(2, '0') + DateTime.Now.Minute.ToString().PadLeft(2, '0') + DateTime.Now.Second.ToString().PadLeft(2, '0');
                element.Attribute("CHANGE_USERID").Value = "site_controlm_acc";

                if (controlMConfiguration.Name != "PROD")
                {
                    element.Elements().Where(n => n.Name.LocalName == "CONTROL").Single().Attribute("NAME").Value = "ATS_EXPURGO_RSCI_EVENTUAL";
                }
                
                if (process.JobName == "LIBERA_BUILD_FORGE_RISCO")
                {
                    element.Attribute("APPLICATION").Value = "LIBERA_BF_RISCO";
                    element.Add(new XAttribute("DAYSCAL", "WORKDAYS"));
                    element.Attribute("CONFIRM").Value = "1";
                    element.Attribute("WEEKDAYS").Remove();
                    element.Attribute("WEEKSCAL").Remove();
                    //element.Attribute("MEMLIB").Remove();
                    element.Attribute("MEMNAME").Remove();
                }

                if (process.JobName == "LIBERA_RISCO_CREDITO")
                {
                    element.Attribute("APPLICATION").Value = "LIBERA_RISCO_CREDITO";
                    element.Attribute("CONFIRM").Value = "1";
                    //element.Attribute("MEMLIB").Remove();
                    element.Attribute("MEMNAME").Remove();
                    element.Attribute("INTERVAL").Value = "00000M";
                }

                if (process.JobName == "RSCISI00DP")
                {
                    element.Add(new XAttribute("TIMEFROM", "0230"));
                    element.Add(new XAttribute("TIMETO", ">"));
                }

                XElement quantitative = element.Elements().Single(e => e.Name.LocalName == "QUANTITATIVE" && e.Attribute("NAME").Value == "RSCI_PROD");
                quantitative.Attribute("NAME").Value = "RSCI_" + controlMConfiguration.Name;

                AddDependency(processes, controlMConfiguration, process, jobName, element);

                var parameter4 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM4")).Single().Attribute("VALUE");
                var parameter5 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.Equals("%%PARM5")).Single().Attribute("VALUE");

                if (process.JobName == "RSCIS064DP")
                {
                    parameter4.Value = "-tipo:agendar";
                    parameter5.Value = "-sistema:" + controlMConfiguration.SystemId;
                }
                else
                {
                    parameter4.Value = "-tipo:comando";
                    parameter5.Value = "-id:" + process.ProcessId;
                }

                var parameter9 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM9")).Single().Attribute("VALUE");
                parameter9.Value = controlMConfiguration.Type;

                var domail = element.Descendants().Where(n => n.Name.LocalName == "DOMAIL");

                foreach (var mail in domail)
                {
                    string message = mail.Attribute("MESSAGE").Value;

                    message = string.Format(message, description.ToUpper());
                    message = (message.Length - 4).ToString().PadLeft(4, '0') + message;

                    if (process.GroupId == "Arquivos")
                    {
                        message = string.Format("Arquivo {0} não encontrado no diretório de origem, verificar log anexo. 00000020Jobname - %%JOBNAME 00000016Data -  %%ODATE 00000013Hora - %%TIME00000016IBBA - Control-M", process.ProcessName);
                        mail.Attribute("MESSAGE").Value = message.Length.ToString().PadLeft(4, '0') + message;
                        mail.Attribute("SUBJECT").Value = "[CTM] *** Alerta de Erro: RSCI: Arquivo não encontrado no diretório de origem ***";
                    }
                    else
                    {
                        mail.Attribute("MESSAGE").Value = message;

                        int id = 0;
                        string subject = string.Empty;

                        if (int.TryParse(process.ProcessId, out id))
                        {
                            subject = string.Format(mail.Attribute("SUBJECT").Value, "Grupo: {0} - Processo: {1} - Nome do Job: {2}");
                            subject = string.Format(subject, process.GroupId, process.ProcessId, jobName);
                        }
                        else
                        {
                            subject = string.Format(mail.Attribute("SUBJECT").Value, "Grupo: {0} - Nome do Job: {1}");
                            subject = string.Format(subject, process.GroupId.ToUpper(), jobName);
                        }

                        mail.Attribute("SUBJECT").Value = subject;
                    }

                    switch (mail.Parent.Attribute("CODE").Value)
                    {
                        case "*MSG_Sucesso*":
                            mail.Attribute("DEST").Value = controlMConfiguration.SuccessEmailAddress;
                            break;
                        case "*MSG_ErroProg*":
                            mail.Attribute("DEST").Value = controlMConfiguration.ErrorEmailAddress;
                            break;
                        case "*MSG_Semarq_Prog*":
                            mail.Attribute("DEST").Value = controlMConfiguration.ErrorEmailAddress;
                            break;
                    }
                }

                var onSuccess = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_Sucesso*")).Single();

                if (string.IsNullOrEmpty(onSuccess.Element("DOMAIL").Attribute("DEST").Value) || (controlMConfiguration.Name == "PROD" && process.TaskType != "Dummy" && process.TaskType != "MaybeDummy"))
                {
                    onSuccess.Element("DOMAIL").Remove();
                }

                if (process.ProcessId == "RSCIN001DP" || process.GroupId == "Arquivos")
                {
                    //element.Add(new XAttribute("DOCLIB", @"\\BBACTMC2\JOBCTL\%%PARM9.\RSCI\DOCLIB"));                    
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM3")).Single().Attribute("VALUE").Value = "%%TIME";                                        
                }

                if (process.GroupId == "Arquivos")
                {
                    //element.Add(new XAttribute("DOCMEM", "%%JOBNAME..TXT"));
                    element.Add(new XAttribute("DAYSCAL", "WORKDAYS"));
                    var on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_Semarq_Prog*")).Single();
                    on.Attribute("CODE").Value = "*MSG_SemArq*";
                    on.Element("DO").Attribute("ACTION").Value = "OK";
                    on.Element("DOMAIL").Remove();

                    on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_ErroProg*")).Single();
                    on.Attribute("CODE").Value = "*MSG_Erromov*";

                    element.Attribute("MAXWAIT").Value = "0";
                    element.Attribute("CYCLIC").Value = "1";
                    element.Attribute("INTERVAL").Value = "00005M";
                    element.Attribute("MEMNAME").Value = string.Format("RSCIS003D{0}.CMD", controlMConfiguration.JobNameSuffix);
                    element.Add(new XAttribute("TIMEFROM", "0100"));
                    element.Add(new XAttribute("TIMETO", ">"));                    
                    element.Attribute("WEEKDAYS").Remove();
                    element.Attribute("WEEKSCAL").Remove();                    
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM2")).Single().Attribute("VALUE").Value = "%%DATE";
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM3")).Single().Attribute("VALUE").Value = "%%TIME";
                    element.Attribute("PAR").Value = @"\\%%PARM51.\JOBCTL\%%PARM9.\%%PARM50.\LOG\%%JOBNAME._%%ODATE._%%TIME..TXT";

                    //element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM4")).Single().Attribute("VALUE").Value = Path.GetFileName(process.SourcePath);
                    //element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM5")).Single().Attribute("VALUE").Value = Path.GetDirectoryName(process.SourcePath);
                    //element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM6")).Single().Attribute("VALUE").Value = Path.GetDirectoryName(process.DestinationPath);

                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM4")).Single().Attribute("VALUE").Value = process.ProcessName;
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.Equals("%%PARM5")).Single().Remove();
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM6")).Single().Remove();
                    element.Elements().Where(n => n.Name.LocalName == "CONTROL").Single().Remove();
                }

                if (process.ProcessId == "RSCIN001DP")
                {
                    //element.Add(new XAttribute("DOCMEM", "%%JOBNAME.TXT"));
                    //element.Add(new XAttribute("CMDLINE", "_sleep 300"));
                    element.Attribute("MEMNAME").Value = "RSCIN001DP.CMD";
                    element.Attribute("NODEID").Value = "BBAPROD4";
                    element.Attribute("MAXWAIT").Value = "30";
                    element.Attribute("PAR").Value = @"\\%%PARM51.\JOBCTL\%%PARM9.\%%PARM50.\LOG\%%JOBNAME._%%ODATE..TXT";
                    element.Elements().Single(e => e.Name.LocalName == "QUANTITATIVE" && e.Attribute("NAME").Value == "RSCI_" + environment).Attribute("NAME").Value = "CONNECT_UPLOAD";
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM2")).Single().Attribute("VALUE").Value = "%%ODATE";
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM4")).Single().Remove();
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.Equals("%%PARM5")).Single().Remove();
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT2" && n.Attribute("NAME").Value.StartsWith("%%PARM6")).Single().Remove();
                    element.Attribute("IND_CYCLIC").Remove();

                    element.Descendants().Where(n => n.Name.LocalName == "ON").ToList().ForEach(n => n.Remove());

                    element.Add(XElement.Parse(@"
                        <ON CODE='*MSG_Sucesso*' STMT='*'>
                              <DOMAIL ATTACH_SYSOUT='Yes' DEST='IBBA-ProcessamentoRisco@corp.bba.com.br' MESSAGE='0079Arquivo  IBBAM6_FX_ENTRADA.txt  para Itau  transmitido com sucesso para o Itau.00000066Src File          =&gt; \\BBAPROD4\ERISCOPR\Itau\IBBAM6_FX_ENTRADA.tx0000000000000000000000000000000000000000000000000000000000000006)0000000000019obname - %%JOBNAME000000014ata - %%ODATE000000012ora - %%TIME' SUBJECT='[CTM] *** Alerta: Sucesso: Processo transmissão de arquivo RSCIN001DP ***' URGENCY='R' />
                        </ON>"));

                    element.Add(XElement.Parse(@"
                        <ON CODE='*MSG_Erro_ndm*' STMT='*'>
                            <DOMAIL ATTACH_SYSOUT='Yes' DEST='IBBA-ProcessamentoRisco@corp.bba.com.br' MESSAGE='0065Erro na transmissao do arquivo IBBAM6_FX_ENTRADA.txt para o Itau.00000066Src File          =&gt; \\BBAPROD4\ERISCOPR\Itau\IBBAM6_FX_ENTRADA.tx0000000000000000000000000000000000000000000000000000000000000006)0000000000019obname - %%JOBNAME000000014ata - %%ODATE000000012ora - %%TIME' SUBJECT='[CTM] *** Alerta: Erro:   Processo transmissão de arquivo RSCIN001DP ***' URGENCY='V' />
                            <DO ACTION='NOTOK' />
                        </ON>"));

                    element.Add(XElement.Parse(@"
                        <ON CODE='*MSG_Erro_acessa*' STMT='*'>
                            <DOMAIL ATTACH_SYSOUT='Yes' DEST='IBBA-ProcessamentoRisco@corp.bba.com.br' MESSAGE='0084Nao exsite arquivo o IBBAM6_FX_ENTRADA.txt no direotio de origem para envio ao Itau.00000066Src File          =&gt; \\BBAPROD4\ERISCOPR\Itau\IBBAM6_FX_ENTRADA.tx0000000000000000000000000000000000000000000000000000000000000006)0000000000019obname - %%JOBNAME000000014ata - %%ODATE000000012ora - %%TIME' SUBJECT='[CTM] *** Alerta: Erro:  Processo transmissão de arquivo RSCIN001DP ***' URGENCY='R' />
                            <DO ACTION='NOTOK' />
                        </ON>"));

                    element.Add(XElement.Parse(@"
                        <ON CODE='*MSG_Semarquivo*' STMT='*'>
                            <DOMAIL ATTACH_SYSOUT='Yes' DEST='IBBA-ProcessamentoRisco@corp.bba.com.br' MESSAGE='0084Nao exsite arquivo o IBBAM6_FX_ENTRADA.txt no direotio de origem para envio ao Itau.00000066Src File          =&gt; \\BBAPROD4\ERISCOPR\Itau\IBBAM6_FX_ENTRADA.tx0000000000000000000000000000000000000000000000000000000000000006)0000000000019obname - %%JOBNAME000000014ata - %%ODATE000000012ora - %%TIME' SUBJECT='[CTM] *** Alerta: Sucesso:  Processo transmissão de arquivo RSCIN001DP ***' URGENCY='R' />
                        </ON>"));

                    element.Add(XElement.Parse(@"
                        <ON CODE='*MSG_Erro_move*' STMT='*'>
                            <DOMAIL ATTACH_SYSOUT='Yes' DEST='IBBA-ProcessamentoRisco@corp.bba.com.br' MESSAGE='0067Erro ao mover o arquivoIBBAM6_FX_ENTRADA.txt no direotio de origem.00000066Src File          =&gt; \\BBAPROD4\ERISCOPR\Itau\IBBAM6_FX_ENTRADA.tx0000000000000000000000000000000000000000000000000000000000000006)0000000000019obname - %%JOBNAME000000014ata - %%ODATE000000012ora - %%TIME' SUBJECT='[CTM] *** Alerta: Erro:  Processo transmissão de arquivo RSCIN001DP ***' URGENCY='R' />
                            <DO ACTION='NOTOK' />
                        </ON>"));

                    element.Add(XElement.Parse(@"<SHOUT DEST='ecs' MESSAGE='Job %%JOBNAME executando a mais de 10 minutos.' TIME='&gt;010' URGENCY='R' WHEN='EXECTIME' />"));
                    element.Add(XElement.Parse(@"<SHOUT DEST='ecs' MESSAGE='Job %%JOBNAME executando a mais de 20 minutos.' TIME='&gt;020' URGENCY='R' WHEN='EXECTIME' />"));
                    element.Add(XElement.Parse(@"<SHOUT DEST='ecs' MESSAGE='Job %%JOBNAME executando a mais de 30 minutos.' TIME='&gt;030' URGENCY='R' WHEN='EXECTIME' />"));
                }

                if (process.ProcessId != "RSCISBI0DP")
                {
                    tableElement.Add(element);
                }
            }

            XElement elementExtra = XElement.Parse(@"
                        <JOB APPL_FORM='CONTROL-M BIM' APPL_TYPE='BIM' APPL_VER='1' APPLICATION='BBAMTSN_NLB_RSCI' APR='1' AUG='1' AUTOARCH='0' CM_VER='6.2.01' CONFIRM='0' CRITICAL='0' CYCLIC='0' CYCLIC_TOLERANCE='0' CYCLIC_TYPE='Interval' DAYS_AND_OR='OR' DEC='1' DESCRIPTION='TESTE - Monitora Grupo FINAME' DOCLIB='http://gsti.itau/maximo/ui/?event=loadapp&amp;value=change&amp;uniqueid=4288596&amp;uisessionid=804' FEB='1' GROUP='NORISKSBIM' IND_CYCLIC='START' INTERVAL='00000M' JAN='1' JOBNAME='RSCISBI0DP' JUL='1' JUN='1' MAR='1' MAXDAYS='0' MAXRERUN='0' MAXRUNS='0' MAXWAIT='4' MAY='1' MEMNAME='ServiceName' MULTY_AGENT='N' NODEID='BBAMTSN_NLB' NOV='1' OCT='1' OWNER='controlm' PARENT_TABLE='BBAMTSN_NLB_RSCI_SYSTEM' PRIORITY='AA' RETRO='0' RULE_BASED_CALENDAR_RELATIONSHIP='OR' SEP='1' SHIFT='IGNOREJOB' SHIFTNUM='+00' SYSDB='0' TASKTYPE='Dummy' USE_INSTREAM_JCL='N' WEEKDAYS='1,2,3,4,5' WEEKSCAL='ALLDAYS'>
                          <AUTOEDIT2 NAME='%%BIM-DUE_TIME' VALUE='08:00,0' />
                          <AUTOEDIT2 NAME='%%BIM-EVENTS' VALUE='SLate1|Fail2|' />
                          <AUTOEDIT2 NAME='%%BIM-Fail2' VALUE='Mail  To#bancobbaproducao@itaubba.com.br;producao@itaubba.com.br;IBBA-Control-M@itaubba.com.br Subject#LINK7 Msg#LINK8' />
                          <AUTOEDIT2 NAME='%%BIM-LINK3' VALUE='Service %%SERVICE_NAME Atrasado.' />
                          <AUTOEDIT2 NAME='%%BIM-LINK4' VALUE='Job %%SERVICE_NAME esta em atraso. O prazo do termino é %%SERVICE_DUE_TIME a estimativa  e %%SERVICE_EXPECTED_END_TIME. Os seguintes job(s) são problematicos: %%PROBLEMATIC_JOBS.' />
                          <AUTOEDIT2 NAME='%%BIM-LINK7' VALUE='Service %%SERVICE_NAME: Job failed on service path.' />
                          <AUTOEDIT2 NAME='%%BIM-LINK8' VALUE='The service %%SERVICE_NAME contains failed job(s). The following job(s) are problematic: %%PROBLEMATIC_JOBS.' />
                          <AUTOEDIT2 NAME='%%BIM-NEXT_LINK' VALUE='11' />
                          <AUTOEDIT2 NAME='%%BIM-SENSITIVITY' VALUE='3sigma' />
                          <AUTOEDIT2 NAME='%%BIM-SERVICE_NAME' VALUE='NORISKSBIM' />
                          <AUTOEDIT2 NAME='%%BIM-SERVICE_PRIORITY' VALUE='3' />
                          <AUTOEDIT2 NAME='%%BIM-SLate1' VALUE='Mail  To#bancobbaproducao@itaubba.com.br;producao@itaubba.com.br;IBBA-Control-M@itaubba.com.br Subject#LINK3 Msg#LINK4' />                          
                          <QUANTITATIVE NAME='INIT' QUANT='1' />
                        </JOB>");

            elementExtra.Attribute("JOBNAME").Value = ReplaceJobName(elementExtra.Attribute("JOBNAME").Value, elementExtra.Attribute("TASKTYPE").Value, controlMConfiguration.JobNameSuffix).Replace("#", "");
            elementExtra.Attribute("PARENT_TABLE").Value = controlMConfiguration.TableName;
            elementExtra.Attribute("NODEID").Value = controlMConfiguration.NodeId;
            elementExtra.Attribute("APPLICATION").Value = controlMConfiguration.Application;

            AddDependency(processes, controlMConfiguration, processes.Find(g => g.ProcessId == "RSCISBI0DP"), elementExtra.Attribute("JOBNAME").Value, elementExtra);

            tableElement.Add(elementExtra);

            document.Save(fileName);
        }

        private static void AddDependency(List<ProcessEntity> processes, ControlMConfigurationElement controlMConfiguration, ProcessEntity process, string jobName, XElement element)
        {
            XElement quantitative = element.Elements().Single(e => e.Name.LocalName == "QUANTITATIVE" && e.Attribute("NAME").Value == "INIT");
            
            foreach (var jobDependency in process.Successors)
            {
                var job = processes.Find(g => g.ProcessId == jobDependency);

                XElement outcond = new XElement("OUTCOND");
                XAttribute name = new XAttribute("NAME", jobName + "-" + ReplaceJobName(job != null ? job.JobName : jobDependency, job != null ? job.TaskType : "", controlMConfiguration.JobNameSuffix));
                XAttribute odate = new XAttribute("ODATE", "ODAT");
                XAttribute sign = new XAttribute("SIGN", "ADD");

                outcond.Add(name);
                outcond.Add(odate);
                outcond.Add(sign);

                quantitative.AddAfterSelf(outcond);

                if (process.GroupId == "Arquivos")
                {
                    XElement docond = new XElement("DOCOND");
                    XAttribute namedocond = new XAttribute("NAME", name.Value + "-LB");

                    XElement doe = new XElement("DO");
                    XAttribute action = new XAttribute("ACTION", "SPCYC");

                    docond.Add(namedocond);
                    docond.Add(odate);
                    docond.Add(sign);

                    doe.Add(action);

                    var on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_Sucesso*")).Single();
                    on.Add(docond);
                    on.Add(doe);
                }
            }

            foreach (var jobDependency in process.Predecessors)
            {
                var processDependency = processes.Find(g => g.ProcessId == jobDependency);

                XAttribute name = new XAttribute("NAME", ReplaceJobName(processDependency.JobName, processDependency.TaskType, controlMConfiguration.JobNameSuffix) + "-" + jobName);
                XAttribute odate = new XAttribute("ODATE", "ODAT");

                XElement outcond = new XElement("OUTCOND");
                XAttribute sign = new XAttribute("SIGN", "DEL");
                outcond.Add(name);
                outcond.Add(odate);
                outcond.Add(sign);
                quantitative.AddAfterSelf(outcond);

                XElement incond = new XElement("INCOND");
                XAttribute and = new XAttribute("AND_OR", "AND");
                incond.Add(and);
                incond.Add(name);
                incond.Add(odate);
                element.AddFirst(incond);

                if (processDependency.GroupId == "Arquivos")
                {
                    XAttribute nameLB = new XAttribute("NAME", name.Value + "-LB");

                    XElement outcondLB = new XElement("OUTCOND");
                    outcondLB.Add(nameLB);
                    outcondLB.Add(odate);
                    outcondLB.Add(sign);
                    quantitative.AddAfterSelf(outcondLB);

                    XElement incondLB = new XElement("INCOND");
                    incondLB.Add(and);
                    incondLB.Add(nameLB);
                    incondLB.Add(odate);
                    element.AddFirst(incondLB);
                }
            }
        }

        private static string ReplaceJobName(string jobName, string taskType, string jobNameSuffix)
        {
            string job = jobName;

            if (jobName.EndsWith("DP"))
            {
                job = jobName.Substring(0, jobName.Length - 1) + jobNameSuffix;
            }

            if (taskType.StartsWith("Maybe"))
            {
                job = "#" + job;
            }

            return job;
        }

        public static XElement Sort(XElement element)
        {
            var elements = from e in element.Elements().OrderBy(e => e.Attributes().Any(a => a.Name.LocalName == "NAME") ? e.Attributes().Single(a => a.Name.LocalName == "NAME").Value : "")
                           orderby e.Name.LocalName
                           select Sort(e);

            XElement newElement = new XElement(element.Name, elements);

            if (element.HasAttributes)
            {
                foreach (XAttribute attrib in element.Attributes().OrderBy(a => a.Name.LocalName))
                {
                    newElement.SetAttributeValue(attrib.Name, attrib.Value);
                }
            }

            return newElement;
        }

        public static XDocument Sort(XDocument file)
        {
            return new XDocument(Sort(file.Root));
        }

        public static XElement EqualizeElement(XElement jobNode)
        {
            XElement element = Sort(jobNode);

            if (element.Attribute("CREATION_DATE") != null)
                element.Attribute("CREATION_DATE").Remove();

            if (element.Attribute("CREATION_TIME") != null)
                element.Attribute("CREATION_TIME").Remove();

            if (element.Attribute("CREATION_USER") != null)
                element.Attribute("CREATION_USER").Remove();

            if (element.Attribute("CHANGE_DATE") != null)
                element.Attribute("CHANGE_DATE").Remove();
            
            if (element.Attribute("CHANGE_TIME") != null)
                element.Attribute("CHANGE_TIME").Remove();
            
            if (element.Attribute("CHANGE_USERID") != null)
                element.Attribute("CHANGE_USERID").Remove();
            
            if (element.Attribute("AUTHOR") != null)
                element.Attribute("AUTHOR").Remove();
            
            //element.Descendants().Where(n => n.Name.LocalName == "DOMAIL").ToList().ForEach(e => e.Remove());

            return element;
        }

        public static void Save(XDocument document, List<XElement> elements, string fileName)
        {
            XDocument documentOrdered = new XDocument(document);
            documentOrdered.Element("DEFTABLE").Element("TABLE").RemoveNodes();
            documentOrdered.Element("DEFTABLE").Element("TABLE").Add(elements);
            documentOrdered = Sort(documentOrdered);
            documentOrdered.Save(GetFileNameSorted(fileName));
        }

        public static string GetFileNameSorted(string fileName)
        {
            return Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + "_SORTED" + Path.GetExtension(fileName));
        }

        private static void WriteProcessDependency(List<ProcessEntity> processes)
        {
            int number = 0;

            foreach (ProcessEntity process in processes)
            {
                foreach (string predecessor in process.Predecessors)
                {
                    if (int.TryParse(process.ProcessId, out number) && int.TryParse(predecessor, out number))
                    {
                        File.AppendAllText(@"c:\depedencia.sql", "INSERT SRC_PROCESSO_DEPENDENCIA_CTM VALUES (" + process.ProcessId + "," + predecessor + ")" + System.Environment.NewLine);
                    }
                }
            }
        }
    }
}
